from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger
from obs import GetObjectHeader
from obs import ObsClient
import os
from datetime import datetime
import traceback

ak = settings.OBS_ACCESS_KEY
sk = settings.OBS_SECRET_KEY
server = settings.OBS_SERVER

obsClient = ObsClient(
    access_key_id=ak,
    secret_access_key=sk,
    server=server
)

# scheduler = BackgroundScheduler()

def get_obs_num(obs_name):
    try:
        bucketName = obs_name
        # 获取桶的存量信息
        resp = obsClient.getBucketStorageInfo(bucketName)
        # 返回码为2xx时，接口调用成功，否则接口调用失败
        if resp.status < 300:
            print('objectNumber:', resp.body.objectNumber)
            return resp.body.objectNumber
        else:
            print('Get Bucket StorageInfo Failed')
            print('requestId:', resp.requestId)
            print('errorCode:', resp.errorCode)
            print('errorMessage:', resp.errorMessage)
    except:
        print('Get Bucket StorageInfo Failed')
        print(traceback.format_exc())



# def start_scheduler():
#     scheduler.start()

# def schedule_task():
#     # 添加定时任务，每隔10秒触发一次get_obs_data
#     scheduler.add_job(get_obs_data, trigger=IntervalTrigger(seconds=5), id='get_obs_data_job', replace_existing=True)





def index(request):
    try:
        anomaly_num1 = get_obs_num('textile-anomaly')
        anomaly_num = get_obs_num('textile-anomaly2') + anomaly_num1
        normal_num1 = get_obs_num('textile-normal')
        normal_num = get_obs_num('textile-normal2') + normal_num1
    except:
        anomaly_num = 0
        normal_num = 0   
    context = {
        'ano_num': anomaly_num,
        'nor_num': normal_num
    }
    return render(request, 'index.html', context)

@csrf_exempt
def get_latest_data(request):
    anomaly_num1 = get_obs_num('textile-anomaly')
    anomaly_num = get_obs_num('textile-anomaly2') + anomaly_num1
    normal_num1 = get_obs_num('textile-normal')
    normal_num = get_obs_num('textile-normal2') + normal_num1
    data = {
        'ano_num': anomaly_num,
        'nor_num': normal_num
    }
    return JsonResponse(data)


def car_control(request):
    return render(request, 'carContrl.html')

def car(request):
    return render(request, 'car.html')

@csrf_exempt
def get_chart_data(request):
    anomaly_num1 = get_obs_num('textile-anomaly')
    anomaly_num = get_obs_num('textile-anomaly2') + anomaly_num1
    normal_num1 = get_obs_num('textile-normal')
    normal_num = get_obs_num('textile-normal2') + normal_num1
    total = normal_num + anomaly_num
    if request.method == 'GET':
        data = {
            'total_forecast': [140, 70, 120, normal_num],
            'accepted_volume': [33, 35, 27, anomaly_num],
            'total_volume': [147, 105, 147, total]
        }
        return JsonResponse(data)
    return JsonResponse({'status': 'fail', 'reason': 'Invalid request method'}, status=400)

@csrf_exempt
def get_chart_series_data(request):
    if request.method == 'GET':
        normal = get_obs_num('textile-normal') + get_obs_num('textile-normal2')
        anomaly = get_obs_num('textile-anomaly') + get_obs_num('textile-anomaly2')
        normal_data = [70, 120, normal, 54, 76, 133, 140]  # 示例数据
        anomaly_data = [35, 27, anomaly, 13, 8, 23, 33]  # 示例数据

        series = [
            {
                'name': '异常',
                'type': 'line',
                'smooth': True,
                'itemStyle': {'normal': {'areaStyle': {'type': 'default'}}},
                'data': anomaly_data
            },
            {
                'name': '正常',
                'type': 'line',
                'smooth': True,
                'itemStyle': {'normal': {'areaStyle': {'type': 'default'}}},
                'data': normal_data
            }
        ]

        return JsonResponse({'series': series})
    return JsonResponse({'status': 'fail', 'reason': 'Invalid request method'}, status=400)


@csrf_exempt
def get_device_data(request):
    anomaly1 = get_obs_num('textile-anomaly')
    anomaly2 = get_obs_num('textile-anomaly2')
    if request.method == 'GET':
        data = {
            'device_001': anomaly1,
            'device_002': anomaly2,
            'device_003': 50
        }
        return JsonResponse(data)
    return JsonResponse({'status': 'fail', 'reason': 'Invalid request method'}, status=400)

@csrf_exempt
def get_anomaly_data(request):
    if request.method == 'GET':
        data = {
            'categories': ['设备001', '设备002', '设备003'],
            'caseno01': [97, 42, 88],
            'caseno02': [94, 90, 86],
            'caseno03': [77, 32, 75]
        }
        return JsonResponse(data)
    return JsonResponse({'status': 'fail', 'reason': 'Invalid request method'}, status=400)


@csrf_exempt
def get_alerts(request):
    if request.method == 'GET':
        anomaly_num1 = get_obs_num('textile-anomaly')
        anomaly_num2 = get_obs_num('textile-anomaly2')
        current_time = datetime.now().strftime("%m/%d %H:%M")
        # 模拟一些数据
        data = []
        for i in range(anomaly_num1):
            alert = {
                "severity": "异常",
                "road": "设备001",
                "issue": f"{i+1}/{anomaly_num1}" ,
                "time": current_time  # 生成时间
            }
            data.append(alert)
        for i in range(anomaly_num2):
            alert = {
                "severity": "异常",
                "road": "设备002",
                "issue": f"{i+1}/{anomaly_num2}" ,
                "time": current_time  # 生成时间
            }
            data.append(alert)
        return JsonResponse(data, safe=False)
    return JsonResponse({'status': 'fail', 'reason': 'Invalid request method'}, status=400)


# def download_image(bucket_name, object_key, download_dir, save_as):
#     try:
#         if not os.path.exists(download_dir):
#             os.makedirs(download_dir)
        
#         # 下载对象的附加头域
#         headers = GetObjectHeader()
        
#         # 下载到本地的路径, save_as 为包含本地文件名称的全路径
#         download_path = os.path.join(download_dir, save_as)
        
#         # 文件下载
#         resp = obsClient.getObject(bucket_name, object_key, download_path, headers=headers)
        
#         # 返回码为2xx时，接口调用成功，否则接口调用失败
#         if resp.status < 300:
#             print(f'Get Object Succeeded: {object_key}')
#             print(f'Downloaded to: {download_path}')
#         else:
#             print(f'Get Object Failed: {object_key}')
#             print('requestId:', resp.requestId)
#             print('errorCode:', resp.errorCode)
#             print('errorMessage:', resp.errorMessage)
#     except Exception as e:
#         print('Get Object Failed') 
#         print(traceback.format_exc())

# 设置本地下载目录

# def download_latest_images(bucket_name, download_dir, flag):
#     # 获取桶内对象的总数
#     total_objects = get_obs_num(bucket_name)
#     if total_objects < 2:
#         print(f"Not enough objects in {bucket_name} to download 2 images.")
#         return
    
#     # 最新的两张图片对应的文件名
#     latest_image_key = f"{total_objects}.png"
#     second_latest_image_key = f"{total_objects - 1}.png"
    
#     # 下载最新的两张图片
#     if flag ==  "anomaly":
#         download_image(bucket_name, latest_image_key, download_dir, save_as="anomaly1.jpg")
#         download_image(bucket_name, second_latest_image_key, download_dir, save_as="anomaly2.jpg")
#     else:
#         download_image(bucket_name, latest_image_key, download_dir, save_as="original1.jpg")
#         download_image(bucket_name, second_latest_image_key, download_dir, save_as="original2.jpg")


# def get_obs_data():
#     # 立即执行一次任务，并返回结果
#     download_dir = "static/img/latest_images"
#     flag = "anomaly"
#     # 下载 textile-anomaly 桶中的最新两张图片
#     download_latest_images("textile-anomaly", download_dir,flag)
#     # 下载 textile-anomaly-original 桶中的最新两张图片
#     flag = "original"
#     download_latest_images("textile-anomaly-original", download_dir,flag)

# start_scheduler()
# schedule_task()


# 记得测试完后改为后面的代码
# def get_error_data(request):
#     base_dir = './static/img'
#     device1_dir = os.path.join(base_dir, 'device1')
#     device2_dir = os.path.join(base_dir, 'device2')

#     # 获取搜索参数
#     device_id = request.GET.get('device_id', '').strip().lower()

#     error_data = []

#     # 获取 device1 文件夹中的异常图片
#     if not device_id or device_id == 'device1':  # 检查设备编号
#         for file in os.listdir(device1_dir):
#             if file.endswith('anomaly.jpg'):
#                 error_data.append({
#                     'device_id': 'device1',
#                     'image_url': f'/static/img/device1/{file}'
#                 })

#     # 获取 device2 文件夹中的异常图片
#     if not device_id or device_id == 'device2':  # 检查设备编号
#         for file in os.listdir(device2_dir):
#             if file.endswith('anomaly.jpg'):
#                 error_data.append({
#                     'device_id': 'device2',
#                     'image_url': f'/static/img/device2/{file}'
#                 })

#     return JsonResponse(error_data, safe=False)

def get_latest_error(request):
    # 获取图片文件夹路径
    device1_dir = os.path.join(settings.BASE_DIR, 'static', 'img', 'device1')
    device2_dir = os.path.join(settings.BASE_DIR, 'static', 'img', 'device2')

    # 获取当前图片数量
    current_device1_count = len([name for name in os.listdir(device1_dir) if os.path.isfile(os.path.join(device1_dir, name))])
    current_device2_count = len([name for name in os.listdir(device2_dir) if os.path.isfile(os.path.join(device2_dir, name))])

    # 从请求中传递上次的计数
    previous_device1_count = int(request.GET.get('previous_device1_count', 0))
    previous_device2_count = int(request.GET.get('previous_device2_count', 0))

    # 检查是否发生了变化
    if previous_device1_count == 0:
        device1_changed = False
        device2_changed = False
    else:
        device1_changed = current_device1_count != previous_device1_count
        device2_changed = current_device2_count != previous_device2_count

    # 返回当前的计数和是否变化的状态
    response_data = {
        'device1_changed': device1_changed,
        'device2_changed': device2_changed,
        'current_device1_count': current_device1_count,
        'current_device2_count': current_device2_count,
    }

    return JsonResponse(response_data)


def get_error_data(request):
    base_dir = './static/img'
    device1_dir = os.path.join(base_dir, 'device1')
    device2_dir = os.path.join(base_dir, 'device2')

    # 获取搜索参数
    device_id = request.GET.get('device_id', '').strip().lower()

    error_data = []

    # 获取 device1 文件夹中的异常图片
    if not device_id or device_id == 'device1':  # 检查设备编号
        for file in os.listdir(device1_dir):
            if file.endswith('anomaly.jpg'):
                timestamp_str, sequence, _ = file.split('_')
                print(sequence)
                timestamp = datetime.strptime(timestamp_str, '%Y%m%d%H%M%S').strftime('%Y-%m-%d %H:%M:%S')
                error_data.append({
                    'image_id': sequence,
                    'device_id': 'device1',
                    'timestamp': timestamp,  # 从文件名提取的时间戳
                    'image_url': f'/static/img/device1/{file}'
                })

    # 获取 device2 文件夹中的异常图片
    if not device_id or device_id == 'device2':  # 检查设备编号
        for file in os.listdir(device2_dir):
            if file.endswith('anomaly.jpg'):
                timestamp_str, sequence, _ = file.split('_')
                print(sequence)
                timestamp = datetime.strptime(timestamp_str, '%Y%m%d%H%M%S').strftime('%Y-%m-%d %H:%M:%S')
                error_data.append({
                    'image_id': sequence,
                    'device_id': 'device2',
                    'timestamp': timestamp,  # 从文件名提取的时间戳
                    'image_url': f'/static/img/device2/{file}'
                })

    return JsonResponse(error_data, safe=False)










def evaluate(args, category, model, visualizer, global_step=0):
    model.eval()
    with torch.no_grad():
        dataset = MVTecDataset(
            is_train=False,
            mvtec_dir=args.mvtec_path + category + "/test/",
            resize_shape=RESIZE_SHAPE,
            normalize_mean=NORMALIZE_MEAN,
            normalize_std=NORMALIZE_STD,
        )
        dataloader = DataLoader(
            dataset, batch_size=args.bs, shuffle=False, num_workers=args.num_workers
        )
        de_st_IAPS = IAPS().cuda()
        de_st_AUPRO = AUPRO().cuda()
        de_st_AUROC = AUROC().cuda()
        de_st_AP = AveragePrecision().cuda()
        de_st_detect_AUROC = AUROC().cuda()
        seg_IAPS = IAPS().cuda()
        seg_AUPRO = AUPRO().cuda()
        seg_AUROC = AUROC().cuda()
        seg_AP = AveragePrecision().cuda()
        seg_detect_AUROC = AUROC().cuda()

        for _, sample_batched in enumerate(dataloader):
            img = sample_batched["img"].cuda()
            mask = sample_batched["mask"].to(torch.int64).cuda()

            output_segmentation, output_de_st, output_de_st_list = model(img)

            output_segmentation = F.interpolate(
                output_segmentation,
                size=mask.size()[2:],
                mode="bilinear",
                align_corners=False,
            )
            output_de_st = F.interpolate(
                output_de_st, size=mask.size()[2:], mode="bilinear", align_corners=False
            )

            mask_sample = torch.max(mask.view(mask.size(0), -1), dim=1)[0]
            output_segmentation_sample, _ = torch.sort(
                output_segmentation.view(output_segmentation.size(0), -1),
                dim=1,
                descending=True,
            )
            output_segmentation_sample = torch.mean(
                output_segmentation_sample[:, : args.T], dim=1
            )
            output_de_st_sample, _ = torch.sort(
                output_de_st.view(output_de_st.size(0), -1), dim=1, descending=True
            )
            output_de_st_sample = torch.mean(output_de_st_sample[:, : args.T], dim=1)

            de_st_IAPS.update(output_de_st, mask)
            de_st_AUPRO.update(output_de_st, mask)
            de_st_AP.update(output_de_st.flatten(), mask.flatten())
            de_st_AUROC.update(output_de_st.flatten(), mask.flatten())
            de_st_detect_AUROC.update(output_de_st_sample, mask_sample)

            seg_IAPS.update(output_segmentation, mask)
            seg_AUPRO.update(output_segmentation, mask)
            seg_AP.update(output_segmentation.flatten(), mask.flatten())
            seg_AUROC.update(output_segmentation.flatten(), mask.flatten())
            seg_detect_AUROC.update(output_segmentation_sample, mask_sample)

        iap_de_st, iap90_de_st = de_st_IAPS.compute()
        aupro_de_st, ap_de_st, auc_de_st, auc_detect_de_st = (
            de_st_AUPRO.compute(),
            de_st_AP.compute(),
            de_st_AUROC.compute(),
            de_st_detect_AUROC.compute(),
        )
        iap_seg, iap90_seg = seg_IAPS.compute()
        aupro_seg, ap_seg, auc_seg, auc_detect_seg = (
            seg_AUPRO.compute(),
            seg_AP.compute(),
            seg_AUROC.compute(),
            seg_detect_AUROC.compute(),
        )

        visualizer.add_scalar("DeST_IAP", iap_de_st, global_step)
        visualizer.add_scalar("DeST_IAP90", iap90_de_st, global_step)
        visualizer.add_scalar("DeST_AUPRO", aupro_de_st, global_step)
        visualizer.add_scalar("DeST_AP", ap_de_st, global_step)
        visualizer.add_scalar("DeST_AUC", auc_de_st, global_step)
        visualizer.add_scalar("DeST_detect_AUC", auc_detect_de_st, global_step)

        visualizer.add_scalar("DeSTSeg_IAP", iap_seg, global_step)
        visualizer.add_scalar("DeSTSeg_IAP90", iap90_seg, global_step)
        visualizer.add_scalar("DeSTSeg_AUPRO", aupro_seg, global_step)
        visualizer.add_scalar("DeSTSeg_AP", ap_seg, global_step)
        visualizer.add_scalar("DeSTSeg_AUC", auc_seg, global_step)
        visualizer.add_scalar("DeSTSeg_detect_AUC", auc_detect_seg, global_step)

        print("Eval at step", global_step)
        print("================================")
        print("Denoising Student-Teacher (DeST)")
        print("pixel_AUC:", round(float(auc_de_st), 4))
        print("pixel_AP:", round(float(ap_de_st), 4))
        print("PRO:", round(float(aupro_de_st), 4))
        print("image_AUC:", round(float(auc_detect_de_st), 4))
        print("IAP:", round(float(iap_de_st), 4))
        print("IAP90:", round(float(iap90_de_st), 4))
        print()
        print("Segmentation Guided Denoising Student-Teacher (DeSTSeg)")
        print("pixel_AUC:", round(float(auc_seg), 4))
        print("pixel_AP:", round(float(ap_seg), 4))
        print("PRO:", round(float(aupro_seg), 4))
        print("image_AUC:", round(float(auc_detect_seg), 4))
        print("IAP:", round(float(iap_seg), 4))
        print("IAP90:", round(float(iap90_seg), 4))
        print()

        de_st_IAPS.reset()
        de_st_AUPRO.reset()
        de_st_AUROC.reset()
        de_st_AP.reset()
        de_st_detect_AUROC.reset()
        seg_IAPS.reset()
        seg_AUPRO.reset()
        seg_AUROC.reset()
        seg_AP.reset()
        seg_detect_AUROC.reset()


def test(args, category):
    if not os.path.exists(args.log_path):
        os.makedirs(args.log_path)

    run_name = f"DeSTSeg_MVTec_test_{category}"
    if os.path.exists(os.path.join(args.log_path, run_name + "/")):
        shutil.rmtree(os.path.join(args.log_path, run_name + "/"))

    visualizer = SummaryWriter(log_dir=os.path.join(args.log_path, run_name + "/"))

    model = DeSTSeg(dest=True, ed=True).cuda()

    assert os.path.exists(
        os.path.join(args.checkpoint_path, args.base_model_name + category + ".pckl")
    )
    model.load_state_dict(
        torch.load(
            os.path.join(
                args.checkpoint_path, args.base_model_name + category + ".pckl"
            )
        )
    )

    evaluate(args, category, model, visualizer)